﻿using CPPEI.Coolzon.UI.Data;
using CPPEI.Coolzon.UI.Views;
using CPPEI.Coolzon.UI.XProperty.Converters;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CPPEI.Coolzon.UI.Design
{
    /// <summary>
    /// RenderPanel.xaml 的交互逻辑
    /// 此类用于替换RenderView，目前用于设计器中使用
    /// </summary>
    public partial class RenderPanel : UserControl
    {
        /// <summary>
        /// 当前显示的方案
        /// </summary>
        public Metadata.Solution Solution { get; private set; }
        /// <summary>
        /// 当前显示的场景
        /// </summary>
        public Metadata.Scene CurrentScene { get; private set; }
        /// <summary>
        /// 当前显示的区域
        /// </summary>
        public Metadata.Area CurrentArea { get; private set; }

        /// <summary>
        /// 弹出视图
        /// </summary>
        private List<UI.Views.PopView> _popViews;

        /// <summary>
        /// 是否在加载时创建新的组件实例，当弹出一个新的场景时，我们需要创建一个新的场景对象防止一个场景加载到多个renderview中
        /// 到后期应该考虑，一个renderview打包一组场景实例
        /// </summary>
        private bool _isLoadPartFromCache = true;

        #region for design

        /// <summary>
        /// 是否启动设计模式
        /// </summary>
        public bool IsDesignMode { get; private set; }

        public DesignData DesignData { get; private set; }

        #endregion

        public RenderPanel()
        {
            InitializeComponent();

            this.IsDesignMode = false;
            _ctlMainFrame.IsCanScroll = true;
            _ctlMainFrame.DisplayMode = PartFrameDisplayMode.Original;//.HStretch;//.Original;// HStretch;
            _popViews = new List<PopView>();

            DesignData = new DesignData(this, this._ctlLayoutMask, this._ctlDesignBorder);

            this.PreviewMouseDown += RenderPanel_PreviewMouseDown;
        }

        void RenderPanel_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (IsDesignMode && DesignData.DesignState == DesignState.LayoutPart)
            {
                Point pointInScene = e.GetPosition(this._ctlMainFrame.CurrentPart);

                // 获取放置组件的父容器
                DesignData.SelContainerPart = (IPartContainer)this._ctlMainFrame.CurrentPart.GetPartAtPoint(typeof(IPartContainer), pointInScene, this._ctlMainFrame.CurrentPart);
                //Debug.WriteLine("选中容器{0} name:{1}", DesignData.SelContainerPart, DesignData.SelContainerPart.Name);

                DesignData.LMouseDownPointInCanvas = e.GetPosition(_ctlLayoutMask);
                DesignData.LMouseDownPointInContainer = e.GetPosition(DesignData.SelContainerPart.GetContentContainer());

                Canvas.SetLeft(_ctlLayoutRect, DesignData.LMouseDownPointInCanvas.Value.X);
                Canvas.SetTop(_ctlLayoutRect, DesignData.LMouseDownPointInCanvas.Value.Y);

                // 计算设计模式下的左上角偏移值
                DesignData.OffsetToCanvas = new Point(DesignData.LMouseDownPointInCanvas.Value.X - pointInScene.X,
                    DesignData.LMouseDownPointInCanvas.Value.Y - pointInScene.Y);

                Debug.WriteLine("DesignData offsetToCanvas:{0},{1} ptInCanvas:{2},{3} ptInContainer:{4},{5}",
                    DesignData.OffsetToCanvas.X,
                    DesignData.OffsetToCanvas.Y,
                    DesignData.LMouseDownPointInCanvas.Value.X,
                    DesignData.LMouseDownPointInCanvas.Value.Y,
                    DesignData.LMouseDownPointInContainer.X,
                    DesignData.LMouseDownPointInContainer.Y);
            }
            else if (IsDesignMode && DesignData.DesignState == DesignState.SelectedPart)
            {
                Point pointInScene = e.GetPosition(this._ctlMainFrame.CurrentPart);
                // 获取放置组件的父容器
                UI.Part selPart = (Part)this._ctlMainFrame.CurrentPart.GetPartAtPoint(typeof(Part), pointInScene, this._ctlMainFrame.CurrentPart);
                Debug.WriteLine("选中name:{0}", selPart.Name);
                if (selPart != _ctlMainFrame.CurrentPart)
                {
                    DesignData.SelectPart(selPart);
                }
            }
            else if (IsDesignMode)
            {

            }
        }
        
        /// <summary>
        /// 设置显示的方案信息
        /// </summary>
        /// <param name="solution"></param>
        public void SetSolution(Metadata.Solution solution)
        {
            this.Solution = solution;
        }

        #region Design mode switch

        /// <summary>
        /// 启动设计模式
        /// </summary>
        public void EnterDesignMode()
        {
            this.IsDesignMode = true;
            this._ctlMainFrame.SetAutoSize();
        }

        /// <summary>
        /// 退出设计模式
        /// </summary>
        public void ExitDesignMode()
        {
            this.IsDesignMode = false;
        }

        #endregion

        /// <summary>
        /// 切换到场景
        /// </summary>
        /// <param name="sceneName"></param>
        /// <param name="args"></param>
        public void SwitchToScene(string sceneName, OpenSceneArgs args)
        {
            if (CurrentScene != null && CurrentScene.Name == sceneName)
            {
                return;
            }

            Metadata.Scene bingoSceneMetadata = Metadata.SolutionUtil.GetScene(Solution, sceneName);

            if (bingoSceneMetadata != null)
            {
                CurrentScene = bingoSceneMetadata;
                UI.Part scene = null;
                if(CurrentScene.IsShowInNavigation)
                {
                    scene = PartInstanceCache.GetSceneInstance("scene", bingoSceneMetadata, _isLoadPartFromCache);
                }
                else
                {
                    // 不显示在导航上的场面每次都新构建
                    scene = PartInstanceCache.GetSceneInstance("scene", bingoSceneMetadata, false);
                }
                if(args!= null)
                {
                    foreach (string key in args.ParametersString.Keys)
                    {
                        Debug.WriteLine(string.Format("注入属性Name:{0}\tValue:{1}到场景:{2}", key, args.ParametersString[key], scene.Name));
                        scene.Parameters.Set(key, args.ParametersString[key]);
                    }
                }

                if (scene != null)
                {
                    _ctlMainFrame.ShowPart(scene, SwitchAnimationFactory.Create("FADE"));
                }

                scene.XWidth = 6000;
                scene.XHeight = 3000;

                PartContext context = new PartContext(null, Solution, bingoSceneMetadata);
                _ctlMainFrame.Active(context);
                scene.PartSelected += currentPart_PartSelected;
            }
        }

        /// <summary>
        /// 切换显示一个区域
        /// </summary>
        /// <param name="sceneName"></param>
        /// <param name="areaName"></param>
        public void SwitchToArea(string sceneName, string areaName)
        {
            //if (CurrentArea != null && CurrentArea.Name == areaName)
            //{
            //    return;
            //}

            //Metadata.Scene bingoSceneMetadata = Metadata.SolutionUtil.GetScene(Solution, sceneName);
            //Metadata.Area bingoAreaMetadata = Metadata.SolutionUtil.GetArea(Solution, sceneName, areaName);
            //if (bingoAreaMetadata != null)
            //{
            //    CurrentScene = bingoSceneMetadata;
            //    CurrentArea = bingoAreaMetadata;
            //    UI.Part areaPart = PartInstanceCache.GetAreaInstance(bingoSceneMetadata, bingoAreaMetadata);

            //    if (areaPart != null)
            //    {
            //        _ctlMainFrame.ShowPart(areaPart, SwitchAnimationFactory.Create("FADE"));
            //    }
            //    _ctlMainFrame.Active();
            //}
        }

        /// <summary>
        /// 滚动到区域
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="area"></param>
        public void ScrollToArea(Metadata.Scene sceneMetadata, Metadata.Area areaMetadata)
        {
            if (CurrentScene == null || CurrentScene.Name != sceneMetadata.Name)
            {
                return;
            }

            if (sceneMetadata != null)
            {
                CurrentScene = sceneMetadata;
                UI.ScenePart scenePart = _ctlMainFrame.CurrentPart as UI.ScenePart;//PartInstanceCache.GetSceneInstance("scene", sceneMetadata, _isLoadPartFromCache) as UI.ScenePart;

                if (scenePart != null)
                {
                    UI.AreaPart areaPart = scenePart.GetChildPart(areaMetadata.Name, false) as AreaPart;
                    if (areaPart != null)
                    {
                        _ctlMainFrame.ScrollToPart(areaPart);
                    }
                }
                //_ctlMainFrame.Active();
            }
        }

        private void _ctlCheckOriginal_Checked(object sender, RoutedEventArgs e)
        {
            if (sender == _ctlCheckOriginal)
            {
                _ctlMainFrame.DisplayMode = PartFrameDisplayMode.Original;
            }
            else if (sender == _ctlCheckHStretch)
            {
                _ctlMainFrame.DisplayMode = PartFrameDisplayMode.HStretch;
            }
            else if (sender == _ctlCheckVStretch)
            {
                _ctlMainFrame.DisplayMode = PartFrameDisplayMode.VStretch;
            }
            else
            {
                _ctlMainFrame.DisplayMode = PartFrameDisplayMode.Stretch;
            }
            _ctlMainFrame.UpdateDisplayMode();

            if (_ctlMainFrame.FrameSize != null && _ctlMainFrame.ContentSize != null)
            {
                _ctlTextSize.Text = string.Format("{0}-{1}/{2}-{3}", _ctlMainFrame.FrameSize.Width,
                    _ctlMainFrame.FrameSize.Height,
                    _ctlMainFrame.ContentSize.Width,
                    _ctlMainFrame.ContentSize.Height);
            }
        }

        /// <summary>
        /// 切换场景
        /// </summary>
        /// <param name="mode"></param>
        /// <param name="frameName"></param>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <param name="data"></param>
        public void OnSwitch(SwitchMode mode, string frameName, string type, string name, OpenSceneArgs args)
        {
            if (mode == SwitchMode.Pop)
            {
                //CPPEI.Coolzon.UI.Views.RenderView contentView = new CPPEI.Coolzon.UI.Views.RenderView(this);
                //PopView popView = new PopView(contentView);
                //this._ctlLayout.Children.Add(popView);
                //contentView.SwitchToScene(name, args);
                //popView.Close += popView_Close;
                //_popViews.Add(popView);
                //popView.SetTitle(contentView.CurrentScene.Caption);

                //EventBus.Instance.OpenSceneCompleted(mode, frameName, name);
            }
            else
            {
                #region // 关闭弹出层
                for (int index = 0; index < _popViews.Count; index++)
                {
                    _popViews[index].Submit();
                }
                _popViews.Clear();
                #endregion

                SwitchToScene(name, args);
                //EventBus.Instance.OpenSceneCompleted(mode, frameName, name);
            }
        }

        /// <summary>
        /// 退出场景
        /// </summary>
        /// <param name="mode"></param>
        /// <param name="frameName"></param>
        /// <param name="type"></param>
        /// <param name="name"></param>
        public void OnBack(SwitchMode mode, string frameName, string type, string name)
        {
            if (mode == SwitchMode.Pop)
            {
                for (int index = 0; index < _popViews.Count; index++)
                {
                    PopView view = _popViews[index];
                    if (view.GetSceneName() == name)
                    {
                        this._ctlLayout.Children.Remove(view);
                        this._popViews.RemoveAt(index);
                        break;
                    }
                }
            }
            else
            {
                _ctlMainFrame.Back();

                // bug
                CurrentScene = null;
            }
        }

        void popView_Close(View view, bool isCancel)
        {
            this._ctlLayout.Children.Remove(view);
        }

        public void OnScrollToArea(string frameName, Metadata.Solution solution, Metadata.Scene scene, Metadata.Area area)
        {
            ScrollToArea(scene, area);
        }

        /// <summary>
        /// 获取当前显示的组件
        /// </summary>
        /// <returns></returns>
        public UI.Part GetCurrentPart()
        {
            return _ctlMainFrame.CurrentPart;
        }

        /// <summary>
        /// 加在part
        /// </summary>
        /// <param name="scenePart"></param>
        public void PreliminaryLoadPart(UI.ScenePart scenePart, bool isShowActiveXPart)
        {
            this._ctlMainFrame.PreliminaryLoadPart(scenePart, isShowActiveXPart);
        }

        void currentPart_PartSelected(Part part)
        {
            Debug.WriteLine("part:{0} selected", part.Name);
            DesignData.SelectPart(part);
        }

        #region mouse event

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            if (IsDesignMode && DesignData.DesignState == DesignState.LayoutPart)
            {
                Point pointInScene = e.GetPosition(this._ctlMainFrame.CurrentPart);

                // 获取放置组件的父容器
                DesignData.SelContainerPart = (IPartContainer)this._ctlMainFrame.CurrentPart.GetPartAtPoint(typeof(IPartContainer), pointInScene, this._ctlMainFrame.CurrentPart);
                //Debug.WriteLine("选中容器{0} name:{1}", DesignData.SelContainerPart, DesignData.SelContainerPart.Name);

                DesignData.LMouseDownPointInCanvas = e.GetPosition(_ctlLayoutMask);
                DesignData.LMouseDownPointInContainer = e.GetPosition(DesignData.SelContainerPart.GetContentContainer());

                Canvas.SetLeft(_ctlLayoutRect, DesignData.LMouseDownPointInCanvas.Value.X);
                Canvas.SetTop(_ctlLayoutRect, DesignData.LMouseDownPointInCanvas.Value.Y);

                // 计算设计模式下的左上角偏移值
                DesignData.OffsetToCanvas = new Point(DesignData.LMouseDownPointInCanvas.Value.X - pointInScene.X,
                    DesignData.LMouseDownPointInCanvas.Value.Y - pointInScene.Y);

                Debug.WriteLine("DesignData offsetToCanvas:{0},{1} ptInCanvas:{2},{3} ptInContainer:{4},{5}",
                    DesignData.OffsetToCanvas.X,
                    DesignData.OffsetToCanvas.Y,
                    DesignData.LMouseDownPointInCanvas.Value.X,
                    DesignData.LMouseDownPointInCanvas.Value.Y,
                    DesignData.LMouseDownPointInContainer.X,
                    DesignData.LMouseDownPointInContainer.Y);
            }
            else if(IsDesignMode)
            {
                Point pointInScene = e.GetPosition(this._ctlMainFrame.CurrentPart);
                // 获取放置组件的父容器
                UI.Part selPart = (Part)this._ctlMainFrame.CurrentPart.GetPartAtPoint(typeof(Part), pointInScene, this._ctlMainFrame.CurrentPart);
                Debug.WriteLine("选中name:{0}",  selPart.Name);
                if (selPart != _ctlMainFrame.CurrentPart)
                {
                    DesignData.SelectPart(selPart);
                }

            }
            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            if (IsDesignMode && DesignData.DesignState == DesignState.LayoutPart)
            {
                DesignData.LMouseUpActualPoint = e.GetPosition(DesignData.SelContainerPart.GetContentContainer());

                Point pos = DesignData.LMouseDownPointInContainer;
                Size size = new Size(DesignData.LMouseUpActualPoint.X - DesignData.LMouseDownPointInContainer.X,
                    DesignData.LMouseUpActualPoint.Y - DesignData.LMouseDownPointInContainer.Y);
                UI.Part newPart = PartInstanceCache.GetPartInstance(DesignData.SelectedPartLibItem);
                //scenePart.Layout.AddPart(pos, newPart);
                newPart.Name = DesignData.GetPartName();
                newPart.XLeft = pos.X;
                newPart.XTop = pos.Y;
                newPart.XWidth = size.Width;
                newPart.XHeight = size.Height;
                newPart.XIsDesignMode = true;
                //(newPart as UI.AreaPart).IsShowHeader = true;
                //(newPart as UI.AreaPart).Caption = "new part";
                //(newPart as UI.AreaPart).XBorderThickness = new Thickness(1);
                //(newPart as UI.AreaPart).XBorderBrush = new SolidColorBrush(Colors.Red);

                DesignData.SelContainerPart.AddPart(newPart);
                DesignData.AddPart(DesignData.SelContainerPart, newPart);
                DesignData.SelectPart(newPart);
                this._ctlDesignBorder.SetOffset(DesignData.LMouseDownPointInCanvas.Value);
                Debug.WriteLine("add part pos:{0},{1} size:{2},{3}", pos.X, pos.Y, size.Width, size.Height);
                //newPart.Select();

                DesignData.LMouseUpPoint = e.GetPosition(_ctlLayoutMask);

                DesignData.LMouseDownPointInCanvas = null;
                DesignData.SelectedPartLibItem = null;
                DesignData.UpdateState(DesignState.SelectedPart);
                this.Cursor = Cursors.Arrow;

                _ctlLayoutRect.Width = 0;
                _ctlLayoutRect.Height = 0;
                this._ctlLayoutMask.Visibility = System.Windows.Visibility.Hidden;
            }
            else if (IsDesignMode && DesignData.IsResize)
            {
                this.DesignData.EndResize();
            }

            base.OnMouseUp(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (IsDesignMode && DesignData.DesignState == DesignState.LayoutPart
                && DesignData.LMouseDownPointInCanvas != null)
            {
                DesignData.LMouseCurrentPoint = e.GetPosition(_ctlLayoutMask);
                double width = DesignData.LMouseCurrentPoint.X - DesignData.LMouseDownPointInCanvas.Value.X;
                if (width < 0)
                {
                    width = 0;
                }
                double height = DesignData.LMouseCurrentPoint.Y - DesignData.LMouseDownPointInCanvas.Value.Y;
                if (height < 0)
                {
                    height = 0;
                }
                _ctlLayoutRect.Width = width;
                _ctlLayoutRect.Height = height;
            }
            else if (IsDesignMode && DesignData.IsResize)
            {
                Point pointInCanvas = e.GetPosition(_ctlLayoutMask);
                DesignData.ResizePart(DesignData.ResizeDirection, pointInCanvas, DesignData.ResizeOffset);
            }
            base.OnMouseMove(e);
        }

        #endregion

        #region for design
        
        /// <summary>
        /// 选中一个组件库项目,进入放置组件的状态
        /// </summary>
        /// <param name="partLibItem"></param>
        public void SelectPartItem(Metadata.PartLibItem partLibItem)
        {
            if (IsDesignMode)
            {
                DesignData.SelectedPartLibItem = partLibItem;
                DesignData.CurLayoutPartTemplate = PartInstanceCache.GetPartInstance(DesignData.SelectedPartLibItem);
                DesignData.UpdateState(DesignState.LayoutPart);
                DesignData.LMouseDownPointInCanvas = null;
                this.Cursor = Cursors.Cross;

                _ctlLayoutRect.Width = 0;
                _ctlLayoutRect.Height = 0;
                this._ctlLayoutMask.Visibility = System.Windows.Visibility.Visible;
            }
        }

        #endregion
    }
}
